// 背包物品使用相关的WebSocket指令处理器
// 专门处理物品使用相关的功能

import { Injectable } from "@nestjs/common";
import { DeputyGeneralService } from "../services/deputy-general.service";
import { InventoryService } from "../services/inventory.service";
import { CharacterService } from "../services/character.service";
import { SystemMessageService } from "../services/system-message.service";

export type InventoryWsHandler = (
  payload: any,
  helpers: {
    userId: number;
    selectedCharacterId?: number;
    deputyGeneralService: DeputyGeneralService;
    inventoryService: InventoryService;
    characterService: CharacterService;
    systemMessageService: SystemMessageService;
    characterEquipmentInventoryService?: any;
    equipmentGemSocketRepository?: any;
    pushMessage: (message: any) => void;
  }
) => Promise<any> | any;

@Injectable()
export class InventoryWsHandlers {
  constructor(
    private readonly deputyGeneralService: DeputyGeneralService,
    private readonly inventoryService: InventoryService,
    private readonly characterService: CharacterService
  ) {}

  /**
   * 处理物品使用指令
   * 指令格式: {c:1387,d:{gid:69}}
   * gid: 物品ID
   */
  async handleItemUsage(payload: any, helpers: any): Promise<any> {
    try {
      const { gid } = payload;
      const characterId = helpers.selectedCharacterId;

      if (!characterId) {
        return {
          act_id: 1387,
          code: -1,
          msg: "请先选择角色",
        };
      }

      if (!gid) {
        return {
          act_id: 1387,
          code: -1,
          msg: "缺少物品ID参数",
        };
      }

      // 根据物品ID处理不同的物品使用逻辑
      switch (gid) {
        case 69: // 大将军令
        case 331: // 大将军令(绑)
          return await this.handleGeneralTokenUsage(characterId, helpers, gid);
        case 68: // 将军令
        case 141: // 将军令(绑)
          return await this.handleGeneralTokenUsage(characterId, helpers, gid);
        default:
          return {
            act_id: 1387,
            code: -1,
            msg: `未知的物品ID: ${gid}`,
          };
      }
    } catch (error: any) {
      console.error("处理物品使用失败:", error);
      return {
        act_id: 1387,
        code: -1,
        msg: error?.message || "物品使用失败",
      };
    }
  }

  /**
   * 处理将军令/大将军令使用
   * 根据文档：
   * - 大将军令：2.5%获取国土，40%获将才，57.5%获英才
   * - 将军令：100%获英才
   */
  private async handleGeneralTokenUsage(
    characterId: number,
    helpers: any,
    itemId: number
  ): Promise<any> {
    try {
      // 1. 检查背包中是否有对应的物品
      const inventoryItem =
        await this.inventoryService.getCharacterInventoryItem(
          characterId,
          itemId
        );

      if (!inventoryItem || inventoryItem.num <= 0) {
        const itemName = this.getItemName(itemId);
        return {
          act_id: 1387,
          code: -1,
          msg: `背包中没有${itemName}`,
        };
      }

      // 2. 根据物品类型生成副将星级类型
      const starLevel = this.generateStarLevelByItem(itemId);

      // 3. 根据副将星级类型选择对应的基础副将
      const baseDeputy = await this.getRandomBaseDeputyByStarLevel(starLevel);

      if (!baseDeputy) {
        return {
          act_id: 1387,
          code: -1,
          msg: "无法找到对应的副将基础数据",
        };
      }

      // 4. 使用事务处理生成副将和扣除物品
      const deputyResult =
        await this.deputyGeneralService.generateDeputyWithTransaction(
          baseDeputy.id,
          characterId,
          inventoryItem.id,
          inventoryItem.num - 1
        );

      // 5. 检查是否需要发送仓库通知
      const typeName = this.getStarLevelName(starLevel);
      const deputyName = baseDeputy.name || "未知副将";

      if (deputyResult.is_in_warehouse) {
        // 副将被放入仓库，发送系统消息通知
        const warehouseMessage = {
          act_id: 10, // 私信通知标识
          info_id: 1000, // 系统角色ID
          state: 1, // 系统消息类型
        };

        // 构建个人消息体格式
        const personalMessageBody = {
          content: `您的随身副将已满，副将${deputyName}已自动放入驿馆。`,
          date: new Date().toLocaleTimeString("zh-CN", {
            hour: "2-digit",
            minute: "2-digit",
            second: "2-digit",
          }),
          fname: "系统信息",
        };

        // 保存个人消息到系统消息表
        try {
          if (helpers.systemMessageService) {
            await helpers.systemMessageService.savePersonalMessage(
              personalMessageBody, // 直接传入对象，服务内部会自动格式化
              characterId,
              1000, // 系统角色ID
              "系统"
            );
          }
        } catch (error: any) {
          console.error("保存仓库通知消息失败:", error);
          // 即使保存失败，也继续发送通知
        }

        // 发送仓库通知消息
        if (helpers.pushMessage) {
          await helpers.pushMessage(warehouseMessage);
        }
      }

      // 6. 返回成功结果
      return {
        act_id: 1387,
        code: 0,
        data: `成功招募(${typeName}):${deputyName}`,
      };
    } catch (error: any) {
      console.error("使用大将军令失败:", error);
      return {
        act_id: 1387,
        code: -1,
        msg: error?.message || "使用大将军令失败",
      };
    }
  }

  /**
   * 根据物品ID生成副将星级类型
   * 大将军令：1: 国土 (2.5%), 2: 将才 (40%), 3: 英才 (57.5%)
   * 将军令：3: 英才 (100%)
   */
  private generateStarLevelByItem(itemId: number): number {
    // 将军令：100%获得英才
    if (itemId === 68 || itemId === 141) {
      return 3; // 英才
    }

    // 大将军令：随机概率
    if (itemId === 69 || itemId === 331) {
      const random = Math.random() * 100;

      if (random <= 2.5) {
        return 1; // 国土 (2.5%)
      } else if (random <= 42.5) {
        return 2; // 将才 (40%)
      } else {
        return 3; // 英才 (57.5%)
      }
    }

    // 默认返回英才
    return 3;
  }

  /**
   * 获取物品名称
   */
  private getItemName(itemId: number): string {
    const itemNames: Record<number, string> = {
      62: "将军令",
      63: "大将军令",
      141: "将军令(绑)",
      331: "大将军令(绑)",
    };

    return itemNames[itemId] || `物品${itemId}`;
  }

  /**
   * 根据副将星级类型随机获取基础副将数据
   * 从数据库中查询对应star_level的副将基础数据列表，然后随机选择一个
   */
  private async getRandomBaseDeputyByStarLevel(
    starLevel: number
  ): Promise<any | null> {
    try {
      // 通过DeputyGeneralService查询对应star_level的副将基础数据
      const baseDeputies =
        await this.deputyGeneralService.getBaseDeputiesByStarLevel(starLevel);

      if (!baseDeputies || baseDeputies.length === 0) {
        console.warn(`没有找到star_level为${starLevel}的副将基础数据`);
        return null;
      }

      // 从列表中随机选择一个副将
      const randomIndex = Math.floor(Math.random() * baseDeputies.length);
      const selectedDeputy = baseDeputies[randomIndex];

      console.log(
        `从${baseDeputies.length}个star_level=${starLevel}的副将中随机选择了: ${selectedDeputy.name} (ID: ${selectedDeputy.id})`
      );

      return selectedDeputy;
    } catch (error) {
      console.error("获取副将基础数据失败:", error);
      return null;
    }
  }

  /**
   * 获取副将星级类型名称
   */
  private getStarLevelName(starLevel: number): string {
    const typeNames: Record<number, string> = {
      1: "国土",
      2: "将才",
      3: "英才",
      4: "常人",
    };

    return typeNames[starLevel] || "未知";
  }

  /**
   * 处理装备详情查看指令
   * 指令格式: {c:1062,d:{id:133437}}
   * id: 装备ID
   */
  async handleEquipmentDetail(payload: any, helpers: any): Promise<any> {
    try {
      const { id } = payload;
      const characterId = helpers.selectedCharacterId;

      if (!characterId) {
        return {
          act_id: 1062,
          code: -1,
          msg: "请先选择角色",
        };
      }

      if (!id) {
        return {
          act_id: 1062,
          code: -1,
          msg: "装备ID不能为空",
        };
      }

      // 查询装备信息
      const equipment =
        await helpers.characterEquipmentInventoryService.getEquipmentById(
          characterId,
          id
        );

      if (!equipment) {
        return {
          act_id: 1062,
          code: -1,
          msg: "装备不存在",
        };
      }

      // 查询宝石槽信息
      const gemSockets = await helpers.equipmentGemSocketRepository.find({
        where: {
          characterId: characterId,
          equipmentId: id,
        },
        order: { socketSlot: "ASC" },
      });

      // 构建宝石槽字符串
      const stoneSlots = ["空", "空", "空"];
      for (const socket of gemSockets) {
        if (socket.socketSlot >= 1 && socket.socketSlot <= 3) {
          const attributeName = await helpers.inventoryService.getAttributeName(
            socket.gemAttributeType
          );
          stoneSlots[
            socket.socketSlot - 1
          ] = `${attributeName}+${socket.gemAttributeValue}点`;
        }
      }

      // 获取当前角色信息用于填充 roleId 与 roleName
      let roleIdStr = "";
      let roleNameStr = "";
      try {
        const roleId = characterId;
        roleIdStr = String(roleId || "");
        const role = await helpers.characterService.getCharacterById(roleId);
        roleNameStr = role?.name || "";
      } catch {}

      // 构建装备详情数据
      const equipmentDetail = [
        { k: "名称:", v: equipment.name || "" },
        { k: "roleId:", v: roleIdStr },
        { k: "roleName:", v: roleNameStr },
        { k: "图片:", v: equipment.pic || "" },
        { k: "等级:", v: equipment.level?.toString() || "0" },
        { k: "重量:", v: equipment.weight?.toString() || "0" },
        {
          k: "效果:",
          v: equipment.bonusAttack ? `攻击力+${equipment.bonusAttack}` : "",
        },
        { k: "佩带条件:", v: this.buildEquipmentRequirement(equipment) },
        { k: "介绍:", v: equipment.description || equipment.intro || "" },
        { k: "宝石孔:", v: `(${stoneSlots.join(",")})` },
        { k: "是否装备:", v: equipment.status === 1 ? "未装备" : "已装备" },
      ];

      return {
        act_id: 1062,
        code: 0,
        data: equipmentDetail,
      };
    } catch (error: any) {
      console.error("获取装备详情失败:", error);
      return {
        act_id: 1062,
        code: -1,
        msg: error?.message || "获取装备详情失败",
        data: [],
      };
    }
  }

  // 构建装备佩戴条件字符串
  private buildEquipmentRequirement(equipment: any): string {
    const requirements = [];

    if (equipment.reqLevel && equipment.reqLevel > 0) {
      requirements.push(`等级大于${equipment.reqLevel}`);
    }

    if (equipment.reqStrength && equipment.reqStrength > 0) {
      requirements.push(`力量大于${equipment.reqStrength}`);
    }

    if (equipment.reqConstitution && equipment.reqConstitution > 0) {
      requirements.push(`体质大于${equipment.reqConstitution}`);
    }

    if (equipment.reqAgility && equipment.reqAgility > 0) {
      requirements.push(`敏捷大于${equipment.reqAgility}`);
    }

    if (equipment.reqIntelligence && equipment.reqIntelligence > 0) {
      requirements.push(`智力大于${equipment.reqIntelligence}`);
    }

    const requirementStr =
      requirements.length > 0 ? requirements.join(",") : "无要求";

    // 这里可以添加角色属性检查逻辑，暂时返回基本信息
    return `${requirementStr}(可以装备)`;
  }

  /**
   * 处理1056指令 - 查询玩家当前部位可佩戴的装备列表
   * 指令格式: { c:1056, d:{ type:1, pageNum:0 } }
   */
  async handleWearableList(payload: any, helpers: any): Promise<any> {
    try {
      const characterId = helpers.selectedCharacterId;
      if (!characterId) {
        return { act_id: 1056, code: -1, msg: "请先选择角色" };
      }

      const type = Number(payload?.type || 0);
      const pageNum = Number(payload?.pageNum || 0);
      if (!Number.isFinite(type) || type <= 0) {
        return { act_id: 1056, code: -1, msg: "部位类型无效" };
      }

      const svc = helpers.characterEquipmentInventoryService;
      if (!svc || typeof svc.getEquipmentsByBaseType !== "function") {
        return { act_id: 1056, code: -1, msg: "服务未就绪" };
      }

      const { list, total } = await svc.getEquipmentsByBaseType(
        characterId,
        type,
        pageNum,
        20
      );

      // 映射为前端期望字段：id, level, lock, name, status
      // status: 1 已装备，0 未装备
      const mapped = list.map((it: any) => ({
        id: it.id,
        level: it.level,
        lock: false,
        name: it.name,
        status: it.status === 0 ? 1 : 0, // 0=已装备->1，1=未装备->0
      }));

      return { act_id: 1056, code: 0, list: mapped, sum: total };
    } catch (error: any) {
      console.error("查询可佩戴装备列表失败:", error);
      return { act_id: 1056, code: -1, msg: error?.message || "查询失败" };
    }
  }
}

// 导出处理器映射
export const inventoryWsHandlers: Record<number, InventoryWsHandler> = {
  // 1387: 物品使用指令
  1387: async (payload, helpers) => {
    const inventoryHandlers = new InventoryWsHandlers(
      helpers.deputyGeneralService,
      helpers.inventoryService,
      helpers.characterService
    );
    return await inventoryHandlers.handleItemUsage(payload, helpers);
  },

  // 1062: 装备详情查看指令
  1062: async (payload, helpers) => {
    const inventoryHandlers = new InventoryWsHandlers(
      helpers.deputyGeneralService,
      helpers.inventoryService,
      helpers.characterService
    );
    return await inventoryHandlers.handleEquipmentDetail(payload, helpers);
  },
  // 1056: 玩家当前部位可佩戴的装备列表
  1056: async (payload, helpers) => {
    const inventoryHandlers = new InventoryWsHandlers(
      helpers.deputyGeneralService,
      helpers.inventoryService,
      helpers.characterService
    );
    return await inventoryHandlers.handleWearableList(payload, helpers);
  },
};
